from django.contrib.auth.decorators import login_required, permission_required
from django.utils.decorators import method_decorator
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect, reverse
from django.core.paginator import Paginator
from django.db.models import Q
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from datetime import datetime

from django import views

from .models import Student, Grade, StudentDetail
from .forms import LoginForm, RegisterForm, StudentForm, StudentDetailForm


# Create your views here.
def index(request):
    # return HttpResponse('你好，我是第一个视图函数！')
    now = datetime.now()  # 获取当前时间
    l1 = [85, 96, 78]
    student = {'name': '飞', 'age': 18, 'gender': 'Female'}

    js = '<script>alert("1")</script>'
    html = '<h2>我是html代码</h2>'

    # 渲染模板
    return render(request, 'students/index.html', context={
        'now': now,
        'l1': l1,
        'student': student,
        'html': html,
        'js': js,
    })

@login_required
def detail(request, pk):
    # return HttpResponse(f'学号为{id}的学生详情')
    section = '学生详情'
    student = Student.objects.get(pk=pk)
    grades = Grade.objects.all()
    return render(request, 'students/detail.html', context={
        'student': student,
        'grades': grades,
        'section': section,
    })

@method_decorator(login_required, name='get')
class DetailView(views.View):
    # @method_decorator(login_required)
    def get(self, request, pk):
        section = '学生详情'
        student = Student.objects.get(pk=pk)
        grades = Grade.objects.all()
        return render(request, 'students/detail.html', context={
            'student': student,
            'grades': grades,
            'section': section,
        })

# def students_list(request, year, month):
# @login_required
def students_list(request):
    # 搜索功能实现
    # 可能有，可能没有
    search = request.GET.get('search', '').strip()
    if search:
        if search.isdigit():  # 数字类型
            students = Student.objects.filter(Q(qq=search) | Q(phone=search), is_delete=False)
        else:
            students = Student.objects.filter(name=search, is_delete=False)
    else:
        # 获取数据
        # students = Student.objects.all().order_by('-c_time')
        students = Student.objects.filter(is_delete=False).order_by('-c_time')

    # return HttpResponse(f'{year}年{month}月报名的学生列表')
    format_str = '%Y年%m月%d日 %H:%M:%S'
    # 分页
    # 每页多少数据
    per_page = request.GET.get('per_page', 5)
    # 第几页
    page = request.GET.get('page', 1)

    paginator = Paginator(students, per_page)
    students = paginator.get_page(page)
    # print(request.path)
    # response = HttpResponse('hello world！')
    # response.write('成功')
    # 传给前端
    return render(request, 'students/students_list.html', context={
        'students': students,
        'format_str': format_str,
        'page': page,
        'total_page': paginator.num_pages,
        'per_page': per_page,
    })


def test_demo(request):
    response = render(request, 'students/detail.html')
    # url = reverse('students:index') # /students/index/
    # response = redirect(url)
    sex = request.GET.get('sex', '0')
    res = Student.objects.values('name', 'age', 'sex').filter(sex=sex)  # queryset
    data = {'res': list(res)}
    return JsonResponse(data)


def students_subject(request, year, month, subject):
    return HttpResponse(f'{year}年{month}月{subject}科目报名的学生列表')


def student_delete(request, pk):
    student = Student.objects.get(pk=pk)
    student.is_delete = True
    student.save()
    return redirect(reverse('students:list'))

@permission_required('students.add_student', raise_exception=True)
def student_add(request):
    section = "添加学生"
    '''
    1.get请求访问空白的详情页
    2.填写页面
    3.点击提交按钮，post提交信息
    4.拿到提交信息，保存数据库
    5.跳转学生信息页展示全部学生信息
    :param request:
    :return:
    '''
    if request.method == 'GET':
        grades = Grade.objects.all()
        return render(request, 'students/detail.html', context={
            'grades': grades,
            'section': section,
        })
    if request.method == 'POST':
        # 学生表信息的增加
        # 有没有分班
        try:
            grade = Grade.objects.get(pk=request.POST.get('grade'))
        except Exception as e:
            print(e)
            grade = None

        student = Student.objects.create(
            name=request.POST.get('name'),
            age=request.POST.get('age'),
            sex=request.POST.get('sex'),
            qq=request.POST.get('QQ'),
            phone=request.POST.get('phone'),
            grade=grade,
        )
        # 详情信息增加
        StudentDetail.objects.create(
            num=request.POST.get('num'),
            college=request.POST.get('college'),
            student=student,
        )
        return redirect(reverse('students:list'))


def student_edit(request, pk):
    section = '编辑学生信息'
    '''
    1.get请求，获得学生的信息
    2.修改学生信息，post提交信息
    3.更新数据库
    '''
    student = Student.objects.get(pk=pk)
    grades = Grade.objects.all()
    if request.method == 'GET':
        return render(request, 'students/detail.html', context={
            'section': section,
            'student': student,
            'grades': grades,
        })
    if request.method == 'POST':
        # 学生表的更新
        # 有没有分班
        grade_id = request.POST.get('grade')
        try:
            grade = Grade.objects.get(pk=grade_id)
        except Exception as e:
            print(e)
            grade = None

        student.name = request.POST.get('name')
        student.age = request.POST.get('age')
        student.sex = request.POST.get('sex')
        student.qq = request.POST.get('QQ')
        student.phone = request.POST.get('phone')
        # 表关联
        student.grade = grade  # 关联对象是否存在

        # 详情表的更新
        # 学生详情是否存在
        try:
            student_detail = student.detail
        except Exception as e:
            print(e)
            student_detail = StudentDetail()
            student_detail.student = student

        student_detail.num = request.POST.get('num')
        student_detail.college = request.POST.get('college')

        # 保存
        student_detail.save()
        student.save()

        return redirect(reverse('students:list'))


def login_form(request):
    # 跳转到next指向的地址
    next_url = request.GET.get('next')
    if request.user.is_authenticated:
        if next_url:
            return redirect(next_url)
    if request.method == 'GET':
        form = LoginForm()  # 表单类实例化
        return render(request, 'students/login.html', context={
            'form': form,
        })
    if request.method == 'POST':
        '''
        1.获取信息
        2.校验是否合法
        3.合法，允许登录
        '''
        form = LoginForm(request.POST)  # 被填充了的form对象
        if form.is_valid():  # 合法，返回True
            # form.cleaned_data校验后的所有数据
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            # 检验账号是否合法（数据库里有没有）
            auth_user = authenticate(request, username=username, password=password)
            if auth_user is not None:
                # 账号是ok的
                login(request, auth_user)  # 登录session
                # 手动将用户名写入session
                request.session['name'] = username
                # request.session.set_expiry(10)
                if next_url:
                    return redirect(next_url)
                return redirect(reverse('students:index'))
            else:
                # 手动写入错误提示信息
                messages.add_message(request, messages.WARNING, '用户名或者密码不正确')

        return render(request, 'students/login.html', context={'form': form})


def logout_form(request):
    logout(request)
    return redirect(reverse('students:login'))


def register_form(request):
    if request.method == 'GET':
        form = RegisterForm()

    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            password2 = form.cleaned_data.get('password2')
            if password == password2:
                # 要注册成功，就是要把用户信息保存到数据库
                User.objects.create(username=username, password=make_password(password))
                return redirect(reverse('students:login'))
    return render(request, 'students/register.html', context={
        'form': form,
    })

class RegisterView(views.View):
    def get(self, request):
        form = RegisterForm()
        return render(request, 'students/register.html', context={
            'form': form,
        })
    def post(self, request):
        form = RegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            password2 = form.cleaned_data.get('password2')
            if password == password2:
                # 要注册成功，就是要把用户信息保存到数据库
                User.objects.create(username=username, password=make_password(password))
                return redirect(reverse('students:login'))
        return render(request, 'students/register.html', context={
            'form': form,
        })


def edit_form(request, pk):
    student = Student.objects.get(pk=pk)
    if request.method == 'GET':
        form = StudentForm(instance=student)
        # 有没有详情
        try:
            detail_form = StudentDetailForm(instance=student.detail)
        except Exception as e:
            print(e)
            student_detail = StudentDetail()
            student_detail.student = student
            student_detail.save()
            detail_form = StudentDetailForm(instance=student_detail)

    if request.method == 'POST':
        form = StudentForm(request.POST, instance=student)
        detail_form = StudentDetailForm(request.POST, instance=student.detail)

        if form.is_valid() and detail_form.is_valid():
            form.save()
            detail_form.save()
            return redirect(reverse('students:list'))

    return render(request, 'students/detail_form.html', context={
        'form': form,
        'detail_form': detail_form,
    })
